<?php

namespace app\api\controller;

use app\common\controller\Api;
use app\common\model\Third;
use Carbon\Carbon;
use EasyWeChat\Factory;
use fast\Http;
use fast\Random;
use think\Config;
use think\Env;
use think\Exception;
use think\Validate;
use app\common\library\Faceid as FaceIdLib;
use app\admin\model\pt\Person as PersonModel;
use app\admin\model\pt\DutyList as DutyModel;
use app\admin\model\User as UserModel;
use app\admin\model\pt\Job as JobModel;
use think\Log;


// part-time
/**
 * 会员接口
 */
class User extends Api
{
    protected $noNeedLogin = [];
    protected $noNeedRight = '*';

    protected $authUser = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->authUser = $this->auth->getUser();
    }

    public function getUserInfo()
    {
        $userId = $this->authUser->id;

        $user = \app\admin\model\User::get($userId);
        // 获取员工所属岗位
        $person = PersonModel::where('user_id', $userId)->with(['job', 'depart'])->find();
        $jobInfo = [
            'job_name'  => '-',
            'depart_name' => '-',
            'contactor' => '',
            'phone' => '',
            'rel' => 0,
            'confirm_idcard' => 0,
        ];
        $personInfo = [];
        if ($person) {
            $person = $person->toArray();
            if (!empty($person['job'])) {
                $jobInfo['job_name'] = $person['job']['name'];
                $jobInfo['contactor'] = $person['job']['contactor'];
                $jobInfo['phone'] = $person['job']['phone'];
            }
            if (!empty($person['depart'])) {
                $jobInfo['depart_name'] = $person['depart']['name'];
            }
            // 已关联
            $jobInfo['rel'] = 1;
            if ($person['source'] == 'mp_mini') {
                $jobInfo['confirm_idcard'] = empty($person['confirm_idcard']) ? 0 : $person['confirm_idcard'];
            } else {
                // 后台录入的直接是认证通过状态
                $jobInfo['confirm_idcard'] = 1;
            }
            unset($person['job'], $person['depart']);
            $personInfo = $person;
        }
        $baseInfo = [
            'avatar' => ykxImageUrl($user->avatar),
            'nickname' => $user->nickname,
            'gender' => $user->gender ? ($user->gender == 1 ? '男' : '女') : '保密',
        ];

        // 获取打卡配置
        $lng = Config::get('site.lng');
        $lat = Config::get('site.lat');
        $radius = Config::get('site.radius');
        $clockInfo =  [
            'lng'  => $lng,
            'lat'  => $lat,
            'radius' => $radius,
        ];

        $info = [
            'base_info' => $baseInfo,
            'job_info'  => $jobInfo,
            'clock_info' => $clockInfo,
            'person_info' => $personInfo,
        ];

        $this->success('ok', $info);
    }
    
    // 绑定人员
    public function bandPerson()
    {
        if ($this->request->isPost()) {
            $phone = $this->request->post('phone', '');
            if (empty($phone) || !checkPhone($phone)) {
                $this->error('请输入手机号');
            }
            // 查找人员表里是否有对应的人
            $person = PersonModel::where('phone', $phone)->find();
            if (!$person) {
                $this->error('后台资料中查无此号码，请使用方式二添加信息或联系管理员');
            }
            $bandUserId = $person->user_id;
            if ($bandUserId) {
                $this->error('此号码已经被绑定，请联系管理员');
            }
            $person->user_id = $this->authUser->id;
            $person->save();
            $this->success('绑定人员信息成功');
        }
        $this->error('need post method');
    }
    
    // 获取个人信息
    public function getPersonInfo()
    {
        $userId = $this->authUser->id;
        $person = PersonModel::where('user_id', $userId)->find();
        if ($person) {
            $this->error('人员信息不存在');
        }

        $this->success('获取成功', $person->toArray());
        
    }
    
    // 保存基本信息
    // 来源是小程序输入的可以修改
    public function savePersonInfo()
    {
        if ($this->request->isPost()) {
            $userId = $this->authUser->id;
            $phone = $this->request->post('phone', '');
            $sex = $this->request->post('sex', '0');
            $avatar = $this->request->post('avatar', '');
            $nickname = $this->request->post('nickname', '');
            $userName = $this->request->post('user_name', '');
            $idCard = $this->request->post('id_card', '');
            $bankCode = $this->request->post('bank_code', '');
            $bankOpenname = $this->request->post('bank_openname', '');
            $stuImage = $this->request->post('stu_image', '');
            $retiredImage= $this->request->post('retired_image', '');
            $insuranceImage = $this->request->post('insurance_image', '');

            if (empty($phone)) {
                $this->error('手机号未输入');
            }
            if (empty($userName) || empty($idCard) || empty($bankCode) || empty($bankOpenname)) {
                $this->error('请检查要输入的信息');
            }
            if (!empty($phone) && !checkPhone($phone)) {
                $this->error('请输入正确的手机号');
            }

            if (!empty($idCard) && !checkIdCard($idCard)) {
                $this->error('请输入正确的身份证');
            }

            $person = PersonModel::where('user_id', $userId)->find();
            // 已存在人员信息
            if ($person) {
                if ($person->source != 'mp_mini') {
                    $this->error('你的个人信息为后台录入，不可编辑保存');
                }
                // 判断手机号是否修改
                if ($phone != $person->phone) {
                    $checkPerson = PersonModel::where('phone', $phone)->where('user_id', '<>', $userId)->find();
                    if ($checkPerson) {
                        $this->error('输入的手机号已绑定了其他人员信息');
                    }
                }
                // 已实名完成的不能修改姓名和身份证号
                if ($person->confirm_idcard != '1') {
                    $person->user_name = $userName;
                    $person->id_card = $idCard;
                }
            } else {
                $checkPerson = PersonModel::where('phone', $phone)->find();
                // 手机号在人员信息里已存在
                if ($checkPerson) {
                    if ($checkPerson->user_id) {
                        $this->error('输入的手机号已绑定');
                    } else {
                        $this->error('输入的手机号已存在，请使用方式一绑定');
                    }
                }
                $checkIdCard = PersonModel::where('id_card', $idCard)->find();
                if ($checkIdCard) {
                    $this->error('输入的身份证已存在');
                }
                $person = new PersonModel();
                $person->user_id = $userId;
                $person->source = 'mp_mini';
                $person->user_type = 'self';
                $person->user_name = $userName;
                $person->id_card = $idCard;
            }
            $person->sex = $sex; 
            $person->phone = $phone;
            $person->bank_code = $bankCode;
            $person->bank_openname = $bankOpenname;
            if (!empty($stuImage)) {
                $person->stu_image = $stuImage;
            }
            if (!empty($retiredImage)) {
                $person->retired_image = $retiredImage;
            }
            if (!empty($insuranceImage)) {
                $person->insurance_image = $insuranceImage;
            }
            $person->save();
            
            if (!empty($nickname)) {
                $this->authUser->nickname = $nickname;
            }
            if (!empty($avatar)) {
                $this->authUser->avatar = $avatar;
            }
            if (!empty($sex)) {
                $this->authUser->gender = $sex;
            }
            $this->authUser->save();
            $this->success('提交成功'); 
        }
        $this->error('need post method');
    }
    
    // 获取当日工作信息
    public function getCurDateJob()
    {
        $curDateId = date('Ymd');
        $dutyInfo = $this->getCurJob($curDateId);
        $jobInfo = $dutyInfo['job'];
        $dutyInfo['is_clock'] = $jobInfo['salary_mode'] == 'stage' ? 'n' : 'y';
        // 为打卡时记录每次打卡时间
        if (empty($dutyInfo['clock_json'])) {
            $clockJson = [];
        } else {
            $clockJson = json_decode($dutyInfo['clock_json'], true);
        }
        if ($dutyInfo['is_clock'] == 'y') {
            $newClockJson = [];
            foreach ($clockJson as $c) {
                $newClockJson[] = date('H:i', $c);
            }
            $clockJson = $newClockJson;
        }
        $dutyInfo['clock_json'] = $clockJson;
        unset($dutyInfo['job']);

        $this->success('获取成功', $dutyInfo);
    }

    public function saveRoadFee()
    {
        if ($this->request->isPost()) {
            $roadFee = $this->request->post('road_fee', 0);
            $roadImage = $this->request->post('road_image', '');
            if (empty($roadFee)) {
                $this->error('路费不能为0');
            }
            $curDateId = date('Ymd');
            $dutyInfo = $this->getCurJob($curDateId);
            if ($dutyInfo['is_road'] == 'y') {
                $dutyModel = DutyModel::get($dutyInfo['id']);
                $dutyModel->road_fee = $roadFee;
                $dutyModel->road_image = $roadImage;
                $dutyModel->save();
                $this->success('保存成功');
            } else {
                $this->error('不提供路费');
            }
        }
        $this->error('need post method');
    }
    
    // 打卡或输入场次
    public function checkInOut()
    {
        if ($this->request->isPost()) {
            $userId = $this->authUser->id;
            $curDateId = date('Ymd');
            $dutyInfo = $this->getCurJob($curDateId);
            $stage = $this->request->post('stage', 0);
            $note = $this->request->post('note', '');
            $lng = $this->request->post('lng', '');
            $lat = $this->request->post('lat', '');
            // 20241120修改为对应工作的打卡点
            $jobModel = JobModel::where('id', $dutyInfo['pt_job_id'])->where('status', 'normal')->find();
            if (!$jobModel) {
               	Log::write($userId . ", job id:" . $dutyInfo['pt_job_id']);
                $this->error('未获取对应工作信息!');
            }
            $dutyInfo['clock_lnglats'] = $jobModel->clock_lnglats;
            if (!empty($dutyInfo['clock_lnglats'])) {
                if (empty($lng) || empty($lat)) {
                    $this->error('缺少位置参数');
                }
               	Log::write($userId . ":" . $lng . "--" . $lat);
                $checkLngLat = false;
                $lnglats = json_decode($dutyInfo['clock_lnglats'], true);
                foreach ($lnglats as $lnglat) {
                    $dis = calDistance($lng, $lnglat['lng'], $lat, $lnglat['lat']) * 1000;
                    Log::write($userId . ":" . $dis . "--" . $lnglat['radius']);
                    if ($dis <= $lnglat['radius']) {
                        $checkLngLat = true;
                    }
                }
                if (!$checkLngLat) {
                    $this->error('不在打卡点半径范围');
                }
            }
            // 为场次时每次只做更新
            if ($dutyInfo['job']['salary_mode'] == 'stage') {
                $clockJson = [
                    'stage' => $stage,
                    'note' => $note,
                ];
            } else {
                // 为打卡时记录每次打卡时间
                if (empty($dutyInfo['clock_json'])) {
                    $clockJson = [];
                } else {
                    $clockJson = json_decode($dutyInfo['clock_json'], true);
                }
                $clockJson[] = time();
            }
            $dutyModel = DutyModel::get($dutyInfo['id']);
            $dutyModel->clock_json = json_encode($clockJson);
            $dutyModel->save();
            $this->success('保存成功');
            
        }
        $this->error('need post method');
    }
    
    // 获取签到记录
    public function getCheckList()
    {
        if ($this->request->isPost()) {
            // 2023-01;
            $month = $this->request->post('month', '');
            if (empty($month)) {
                $this->error('月份不能为空');
            }
            $personModel = $this->checkPerson();
            $month = date('Ym', strtotime($month));
            $startDate = $month . "01";
            $selectDate = Carbon::parse($startDate);
            $endDate = $selectDate->lastOfMonth()->format('Ymd');
            $dutyModel = DutyModel::where('pt_person_id', $personModel->id)->where('date_id', 'like', '%'.$month.'%')
              ->with('job')
              ->order('date_id', 'asc')->select();
            $monthDuty = [];
            $defautDuty =  [
                    'date' => '',
                    'depart_name' => '',
                    'job_name' => '',
                    'contactor' => '',
                    'phone' => '',
                    'is_road' => '',
                    'road_fee' => '',
                    'is_clock' => '',
                    'clock_json' => [],
                ]; 
            foreach ($dutyModel as $d) {
                $clockJson = json_decode($d->clock_json, true);
                $isClock = $d->job->salary_mode == 'stage' ? 'n' : 'y';
                if ($isClock == 'y') {
                    $newClockJson = [];
                    if (!empty($clockJson)) {
                        foreach ($clockJson as $c) {
                            $newClockJson[] = date('H:i', $c);
                        }
                    }
                    $clockJson = $newClockJson;
                }
                $duty = [
                    'date' => date('Y-m-d', strtotime($d->date_id)),
                    'depart_name' => $d->depart_name,
                    'job_name' => $d->job_name,
                    'contactor' => $d->job->contactor,
                    'phone' => $d->job->phone,
                    'is_road' => $d->is_road,
                    'road_fee' => $d->road_fee,
                    'is_clock' => $isClock,
                    'clock_json' => empty($clockJson) ? [] : $clockJson,
                ]; 
                $monthDuty[$d->date_id] = $duty;
            }
            $monthData = [];
            for($dateId = $startDate; $dateId <= $endDate; $dateId++) {
                if (isset($monthDuty[$dateId])) {
                    $monthData[] = $monthDuty[$dateId];
                } else {
                    $tmp = $defautDuty;
                    $tmp['date'] = date('Y-m-d', strtotime($dateId)); 
                    $monthData[] = $tmp;
                }
            }
            $newMonthDuty = [];
            foreach($monthDuty as $d) {
                $newMonthDuty[] = $d;
            }
            $this->success('获取成功', ['monthData' => $monthData, 'monthDuty' => $newMonthDuty]);
        }
        $this->error('need post method');
    }

    public function checkPersonLive()
    {
        if ($this->request->isPost()) {
            $name = $this->request->post('name', '');
            $idCard = $this->request->post('id_card', '');
            $frontImage = $this->request->post('front_image', '');
            $backImage = $this->request->post('back_image', '');
            if (empty($name) || empty($idCard) || empty($frontImage) || empty($backImage)) {
                $this->error('提交的信息不完整');
            }
            $personModel = $this->checkPerson();
            // 已完成实名
            if ($personModel->confirm_idcard == '1') {
                $this->error('不能重复实名');
            }

            $faceidLib = new FaceIdLib();
            $checkRes = $faceidLib->checkNameAndIdCardByLive($name, $idCard, $personModel->user_id);

            $msg = $checkRes['msg'];
            $data = $checkRes['data'];

            if ($msg != 'ok') {
                $this->error($msg, $data);
            }

            $personModel->biz_token = $data['BizToken'];
            $personModel->confirm_idcard = 0;
            $personModel->confirm_end_time = time() + 5 * 60;
            $personModel->user_name = $name;
            $personModel->id_card = $idCard;
            $personModel->idcard_front_image = $frontImage;
            $personModel->idcard_back_image = $backImage;
            $personModel->save();

            $qrCodeUrl = addon_url('qrcode/index/build', ['text' => $data['Url'], 'size' => 200, 'padding' => 0], '', true);

            $this->success('获取认证信息完成', $qrCodeUrl);
        }

        $this->error('need post method');
    
    }

    public function getDetectPersonLive()
    {
        if ($this->request->isPost()) {
            $bizToken = $this->request->post('biz_token', '');
            if (empty($bizToken)) {
                $this->error('提交的信息不完整');
            }
            $personModel = $this->checkPerson();

            $faceidLib = new FaceIdLib();
            $checkRes = $faceidLib->getDetectInfo($bizToken);

            $msg = $checkRes['msg'];
            $data = $checkRes['data'];

            if ($msg != 'ok') {
                $this->error($msg, $data);
            }
            $textRes = $data['Text'];
            if ($textRes['Comparemsg'] == '成功') {
                // 判断是否与提交的姓名和身份证号一致
                if ($textRes['IdCard'] != $personModel->id_card || $textRes['Name'] != $personModel->user_name) {
                    $personModel->confirm_idcard = 2;
                    $personModel->confirm_desc = '第三方活体认证结果与输入的姓名或身份证不一致';
                    $msg = '失败';
                } else {
                    $personModel->confirm_idcard = 1;
                    $personModel->confirm_desc = '认证成功';
                    $personModel->confirm_time = time();
                    $msg = '成功';
                }
            } else {
                $personModel->confirm_idcard = 2;
                $personModel->confirm_desc = $textRes['ErrMsg'];
                $msg = '失败';
            }
            $personModel->confirm_end_time = 0;
            $personModel->save();

            $this->success($msg, $data);
        }

        $this->error('need post method');
    
    }

    public function mpWeixinDecodePhone()
    {

        if ($this->request->isPost()) {

            $user = $this->auth->getUser();

            $encryptedData = $this->request->post('encryptedData');
            $iv = $this->request->post('iv');
            $doSet = $this->request->post('doSet', 0); //是否保存

            $mpAppid = Env::get('mp.appid');
            $mpAppSecret = Env::get('mp.app_secret');

            $config = [
                'app_id' => $mpAppid,
                'secret' => $mpAppSecret,

                'response_type' => 'array',
                'log' => [
                    'level' => 'debug',
                    'file' => ROOT_PATH . '/runtime/log/wechat.log',
                ],
            ];

            try {
                $app = Factory::miniProgram($config);

                $sessionkey = Third::where('user_id', $user->id)->find()->sessionkey;

                $decryptedData = $app->encryptor->decryptData($sessionkey, $iv, $encryptedData);

                if ($doSet) {
                    $user->mobile = $decryptedData['phoneNumber'];
                    $user->save();
                }

            } catch (\Exception $e) {

                $this->error($e->getMessage(), null, 401);
            }

            $this->success('ok', ['phone' => $decryptedData['phoneNumber']]);
        }
    }


    public function mpWeixinGetPhone()
    {

        if ($this->request->isPost()) {

            $user = $this->auth->getUser();

            $code = $this->request->post('code');
            $doSet = $this->request->post('doSet', 0); //是否保存

            $mpAppid = Env::get('mp.appid');
            $mpAppSecret = Env::get('mp.app_secret');

            $config = [
                'app_id' => $mpAppid,
                'secret' => $mpAppSecret,

                'response_type' => 'array',
                'log' => [
                    'level' => 'debug',
                    'file' => ROOT_PATH . '/runtime/log/wechat.log',
                ],
            ];

            try {
                $app = Factory::miniProgram($config);
                $accessToken = $app->access_token->getToken()['access_token'];

                $url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=$accessToken";

                $headers = ['content-type:application/json'];
                $options = [
                    CURLOPT_HTTPHEADER => $headers
                ];

                $postdata = [
                    'code' => $code,
                ];

                $res = Http::post($url, json_encode($postdata), $options);
                $res = json_decode($res, true);
                if (0 == $res['errcode']) {
                    $phone = $res['phone_info']['phoneNumber'];
                } else {
                    throw new \Exception($res['errmsg']);
                }

                if ($doSet) {
                    $user->mobile = $phone;
                    $user->save();
                }

            } catch (\Exception $e) {

                $this->error($e->getMessage());
            }

            $this->success('ok', ['phone' => $phone]);
        }
    }




    public function checkNameAndIdCard()
    {
        if ($this->request->isPost()) {
            $name = $this->request->post('name', '');
            $idCard = $this->request->post('id_card', '');
            // 如果验证通过后记录信息
            $userId = $this->auth->getUser()->id;
            $userExtend = Extend::where('user_id', $userId)->find();
            if ($userExtend->is_realname == '1') {
                $this->error('不能重复实名', []);
            }

            $faceidLib = new FaceIdLib();
            $checkRes = $faceidLib->checkNameAndIdCard($name, $idCard);

            $msg = $checkRes['msg'];
            $data = $checkRes['data'];

            if ($msg != 'ok') {
                $this->error($msg, $data);
            }
            if ($userExtend) {
                $userExtend->name = $name;
                $userExtend->id_card = $idCard;
                $userExtend->is_realname = 1;
                $userExtend->save();
                // 更新user表
                $user = \app\common\model\User::get($userId);
                $user->birthday = date('Y-m-d', strtotime(substr($idCard, 6, 8)));
                $user->save();
            }
            $this->success('实名成功', $data);
        }

        $this->error('need post method');
    
    }
    
    private function getCurJob($curDateId)
    {
        $personModel = $this->checkPerson();
        $dutyInfo = DutyModel::where('pt_person_id', $personModel->id)->where('date_id', $curDateId)->with('job')->find();
        if (!$dutyInfo) {
            $this->error('未获取到今日工作安排');
        }
        $dutyInfo = $dutyInfo->toArray();
        
        return $dutyInfo; 
    }

    private function checkPerson()
    {
        $userId = $this->authUser->id;
        $personModel = PersonModel::where('user_id', $userId)->find();
        if (!$personModel) {
            $this->error('未获取到人员信息,请先完善用户信息!');
        }
        
        return $personModel; 
    }

}
